#include "LecteurFonction.h"

LecteurFonction::LecteurFonction(LecteurSymbole* ls) : Lecteur(ls) {
    this->arbre = declFonction();
}

Valeur* LecteurFonction::getValeur(stack<Valeur*> & p) {
    if (p.size() != nbParam) {
        cout << "Erreur : Nombre de paramètres incorrect pour la fonction " << this->nom << endl;
        exit(0);
    } else {
        // On applique les paramètres de la fonction à la table des symboles
        for (int i=p.size()-1; i>=0; i--) {
            ts[i]->setValeur(p.top());
            p.pop();
        }
        // On exécute la fonction
        return this->arbre->getValeur();
    }
}

////////////////////////////////////////////////////////////////////////////////

Noeud* LecteurFonction::declFonction() {
    Noeud* decl = NULL;
    sauterSymCour("fonction");
    this->nom = getLs()->getSymCour().getChaine();
    getLs()->suivant();
    sauterSymCour("(");
    ts.chercheAjoute(getLs()->getSymCour());
    nbParam++;
    getLs()->suivant();
    while (getLs()->getSymCour() == ",") {
        getLs()->suivant();
        if (getLs()->getSymCour() == "<VARIABLE>") {
            ts.chercheAjoute(getLs()->getSymCour());
            nbParam++;
            getLs()->suivant();
        } else {
            erreur("<VARIABLE>");
            exit(0);
        }
    }
    sauterSymCour(")");
    sauterSymCour("=");
    decl = expression();
    sauterSymCour(";");
    return decl;
}

////////////////////////////////////////////////////////////////////////////////

Noeud* LecteurFonction::facteur() {
    // <facteur> ::= <ENTIER> | <REEL> | <CARACTERE> | <CHAINE> |
    //               <variable> | <opUnaire> <expBool> | ( <expBool> )

    Noeud* fact = NULL;

    if (getLs()->getSymCour() == "<VARIABLE>" || getLs()->getSymCour() == "<ENTIER>"
            || getLs()->getSymCour() == "<REEL>" || getLs()->getSymCour() == "<CARACTERE>"
            || getLs()->getSymCour() == "<CHAINE>") {
        fact = ts.chercheAjoute(getLs()->getSymCour());
        getLs()->suivant();
    } else if (getLs()->getSymCour() == "-" || getLs()->getSymCour() == "non") {
        Symbole operateur = opUnaire();
        Noeud* exp = expBool();
        // on représente le moins unaire (- facteur) par une soustractin binaire (0 - facteur)
        fact = new NoeudOperateurBinaire(operateur, NULL, exp);
    } else if (getLs()->getSymCour() == "(") {
        getLs()->suivant();
        fact = expBool();
        sauterSymCour(")");
    } else
        erreur("<facteur>");
    return fact;
}

